40c9c468U8EVl0d3G--8YXVg6VJD3g tools/python/xen/xend/EventTypes.py
40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/python/xen/xend/PrettyPrint.py
40e15b7eeQxWE_hUPB2YTgM9fsZ1PQ tools/python/xen/xend/Vifctl.py
+4151594bBq8h-bwTfEt8dbBuojMtcA tools/python/xen/xend/XendAsynchProtocol.py
40c9c4688m3eqnC8fhLu1APm36VOVA tools/python/xen/xend/XendClient.py
40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/python/xen/xend/XendConsole.py
40c9c468WnXs6eOUSff23IIGI4kMfQ tools/python/xen/xend/XendDB.py
40ffc44eGsgTEY355E3nN4mPLZHhMQ tools/python/xen/xend/XendLogging.py
40c9c46854nsHmuxHQHncKk5rAs5NA tools/python/xen/xend/XendMigrate.py
40c9c468M96gA1EYDvNa5w5kQNYLFA tools/python/xen/xend/XendNode.py
+4151594bhib4aUerB2SMKDl-iCtc4Q tools/python/xen/xend/XendProtocol.py
40c9c4686jruMyZIqiaZRMiMoqMJtg tools/python/xen/xend/XendRoot.py
40c9c468xzANp6o2D_MeCYwNmOIUsQ tools/python/xen/xend/XendVnet.py
40c9c468x191zetrVlMnExfsQWHxIQ tools/python/xen/xend/__init__.py
network - default network setup script called by xend at startup.
vif-bridge - default virtual network interface setup script.
xend-config.sxp - default xend configuration file.
-xmdefconfig - default configuration script for 'xm create'.
-xmdefconfig-example - a more complex configuration script for 'xm create'.
-xmdefconfig-netbsd - an 'xm create' configuration script for NetBSD domains.
+xmexample1 - example configuration script for 'xm create'.
+xmexample2 - a more complex configuration script for 'xm create'.
-from xen.xend.XendClient import aserver as server
+from xen.xend.XendClient import getAsynchServer
+server = getAsynchServer()
from xen.xend import PrettyPrint
from xen.sv.HTMLBase import HTMLBase
--- /dev/null
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+from twisted.protocols import http
+from twisted.internet.protocol import ClientCreator
+from twisted.internet.defer import Deferred
+from twisted.internet import reactor
+
+from XendProtocol import XendClientProtocol, XendRequest
+
+class AsynchXendClient(http.HTTPClient):
+ """A subclass of twisted's HTTPClient to deal with a connection to xend.
+ Makes the request when connected, and delegates handling responses etc.
+ to its protocol (usually an AsynchXendClientProtocol instance).
+ """
+ def __init__(self, protocol, request):
+ self.protocol = protocol
+ self.request = request
+
+ def connectionMade(self):
+ request = self.request
+ url = self.request.url
+ self.sendCommand(request.method, url.fullpath())
+ self.sendHeader('Host', url.location())
+ for (k, v) in request.headers.items():
+ self.sendHeader(k, v)
+ if request.data:
+ self.sendHeader('Content-Length', len(request.data))
+ self.endHeaders()
+ if request.data:
+ self.transport.write(request.data)
+
+ def handleStatus(self, version, status, message):
+ return self.protocol.handleStatus(version, status, message)
+
+ def handleHeader(self, key, val):
+ return self.protocol.handleHeader(key, val)
+
+ def handleResponse(self, data):
+ return self.protocol.handleResponse(data)
+
+class AsynchXendClientProtocol(XendClientProtocol):
+ """An asynchronous xend client. Uses twisted to connect to xend
+ and make the request. It does not block waiting for the result,
+ but sets up a deferred that is called when the result becomes available.
+
+ Uses AsynchXendClient to manage the connection.
+ """
+ def __init__(self):
+ self.err = None
+ self.headers = {}
+
+ def xendRequest(self, url, method, args=None):
+ """Make a request to xend. The returned deferred is called when
+ the result is available.
+
+ @param url: xend request url
+ @param method: http method: POST or GET
+ @param args: request arguments (dict)
+ @return: deferred
+ """
+ request = XendRequest(url, method, args)
+ self.deferred = Deferred()
+ clientCreator = ClientCreator(reactor, AsynchXendClient, self, request)
+ clientCreator.connectTCP(url.host, url.port)
+ return self.deferred
+
+ def callErrback(self, err):
+ if not self.deferred.called:
+ self.err = err
+ self.deferred.errback(err)
+ return err
+
+ def callCallback(self, val):
+ if not self.deferred.called:
+ self.deferred.callback(val)
+ return val
+
+ def handleException(self, err):
+ return self.callErrback(err)
+
+ def handleHeader(self, key, val):
+ self.headers[key.lower()] = val
+
+ def getHeader(self, key):
+ return self.headers.get(key.lower())
+
+ def handleResponse(self, data):
+ if self.err: return self.err
+ val = XendClientProtocol.handleResponse(self, data)
+ if isinstance(val, Exception):
+ self.callErrback(val)
+ else:
+ self.callCallback(val)
+ return val
"""
import os
import sys
-import httplib
import types
-from StringIO import StringIO
-
-from twisted.protocols import http
-from twisted.internet.protocol import ClientCreator
-from twisted.internet.defer import Deferred
-from twisted.internet import reactor
-
-from encode import *
import sxp
import PrettyPrint
+from XendProtocol import XendClientProtocol, SynchXendClientProtocol, XendError
DEBUG = 0
-class XendError(RuntimeError):
- """Error class for 'expected errors' when talking to xend.
- """
- pass
-
def fileof(val):
"""Converter for passing configs or other 'large' data.
Handles lists, files directly.
query=query,
frag=frag)
-class XendRequest:
- """A request to xend.
- """
-
- def __init__(self, url, method, args):
- """Create a request. Sets up the headers, argument data, and the
- url.
-
- @param url: the url to request
- @param method: request method, GET or POST
- @param args: dict containing request args, if any
- """
- if url.proto != 'http':
- raise ValueError('Invalid protocol: ' + url.proto)
- (hdr, data) = encode_data(args)
- if args and method == 'GET':
- url.query = data
- data = None
- if method == "POST" and url.path.endswith('/'):
- url.path = url.path[:-1]
-
- self.headers = hdr
- self.data = data
- self.url = url
- self.method = method
-
-class XendClientProtocol:
- """Abstract class for xend clients.
- """
- def xendRequest(self, url, method, args=None):
- """Make a request to xend.
- Implement in a subclass.
-
- @param url: xend request url
- @param method: http method: POST or GET
- @param args: request arguments (dict)
- """
- raise NotImplementedError()
-
- def xendGet(self, url, args=None):
- """Make a xend request using HTTP GET.
- Requests using GET are usually 'safe' and may be repeated without
- nasty side-effects.
-
- @param url: xend request url
- @param data: request arguments (dict)
- """
- return self.xendRequest(url, "GET", args)
-
- def xendPost(self, url, args):
- """Make a xend request using HTTP POST.
- Requests using POST potentially cause side-effects, and should
- not be repeated unless you really want to repeat the side
- effect.
-
- @param url: xend request url
- @param args: request arguments (dict)
- """
- return self.xendRequest(url, "POST", args)
-
- def handleStatus(self, version, status, message):
- """Handle the status returned from the request.
- """
- status = int(status)
- if status in [ http.NO_CONTENT ]:
- return None
- if status not in [ http.OK, http.CREATED, http.ACCEPTED ]:
- return self.handleException(XendError(message))
- return 'ok'
-
- def handleResponse(self, data):
- """Handle the data returned in response to the request.
- """
- if data is None: return None
- type = self.getHeader('Content-Type')
- if type != sxp.mime_type:
- return data
- try:
- pin = sxp.Parser()
- pin.input(data);
- pin.input_eof()
- val = pin.get_val()
- except sxp.ParseError, err:
- return self.handleException(err)
- if isinstance(val, types.ListType) and sxp.name(val) == 'xend.err':
- err = XendError(val[1])
- return self.handleException(err)
- return val
-
- def handleException(self, err):
- """Handle an exception during the request.
- May be overridden in a subclass.
- """
- raise err
-
- def getHeader(self, key):
- """Get a header from the response.
- Case is ignored in the key.
-
- @param key: header key
- @return: header
- """
- raise NotImplementedError()
-
-class SynchXendClientProtocol(XendClientProtocol):
- """A synchronous xend client. This will make a request, wait for
- the reply and return the result.
- """
-
- resp = None
-
- def xendRequest(self, url, method, args=None):
- """Make a request to xend.
-
- @param url: xend request url
- @param method: http method: POST or GET
- @param args: request arguments (dict)
- """
- self.request = XendRequest(url, method, args)
- conn = httplib.HTTPConnection(url.location())
- if DEBUG: conn.set_debuglevel(1)
- conn.request(method, url.fullpath(), self.request.data, self.request.headers)
- resp = conn.getresponse()
- self.resp = resp
- val = self.handleStatus(resp.version, resp.status, resp.reason)
- if val is None:
- data = None
- else:
- data = resp.read()
- conn.close()
- val = self.handleResponse(data)
- return val
-
- def getHeader(self, key):
- return self.resp.getheader(key)
-
-
-class AsynchXendClient(http.HTTPClient):
- """A subclass of twisted's HTTPClient to deal with a connection to xend.
- Makes the request when connected, and delegates handling responses etc.
- to its protocol (usually an AsynchXendClientProtocol instance).
- """
- def __init__(self, protocol, request):
- self.protocol = protocol
- self.request = request
-
- def connectionMade(self):
- request = self.request
- url = self.request.url
- self.sendCommand(request.method, url.fullpath())
- self.sendHeader('Host', url.location())
- for (k, v) in request.headers.items():
- self.sendHeader(k, v)
- if request.data:
- self.sendHeader('Content-Length', len(request.data))
- self.endHeaders()
- if request.data:
- self.transport.write(request.data)
-
- def handleStatus(self, version, status, message):
- return self.protocol.handleStatus(version, status, message)
-
- def handleHeader(self, key, val):
- return self.protocol.handleHeader(key, val)
-
- def handleResponse(self, data):
- return self.protocol.handleResponse(data)
-
-class AsynchXendClientProtocol(XendClientProtocol):
- """An asynchronous xend client. Uses twisted to connect to xend
- and make the request. It does not block waiting for the result,
- but sets up a deferred that is called when the result becomes available.
-
- Uses AsynchXendClient to manage the connection.
- """
- def __init__(self):
- self.err = None
- self.headers = {}
-
- def xendRequest(self, url, method, args=None):
- """Make a request to xend. The returned deferred is called when
- the result is available.
-
- @param url: xend request url
- @param method: http method: POST or GET
- @param args: request arguments (dict)
- @return: deferred
- """
- request = XendRequest(url, method, args)
- self.deferred = Deferred()
- clientCreator = ClientCreator(reactor, AsynchXendClient, self, request)
- clientCreator.connectTCP(url.host, url.port)
- return self.deferred
-
- def callErrback(self, err):
- if not self.deferred.called:
- self.err = err
- self.deferred.errback(err)
- return err
-
- def callCallback(self, val):
- if not self.deferred.called:
- self.deferred.callback(val)
- return val
-
- def handleException(self, err):
- return self.callErrback(err)
-
- def handleHeader(self, key, val):
- self.headers[key.lower()] = val
-
- def getHeader(self, key):
- return self.headers.get(key.lower())
-
- def handleResponse(self, data):
- if self.err: return self.err
- val = XendClientProtocol.handleResponse(self, data)
- if isinstance(val, Exception):
- self.callErrback(val)
- else:
- self.callCallback(val)
- return val
-
class Xend:
"""Client interface to Xend.
"""
{'op' : 'inject',
'event' : fileof(sxpr) })
+def getAsynchXendClientProtocol():
+ """Load AsynchXendClientProtocol on demand to avoid the cost.
+ """
+ global AsynchXendClientProtocol
+ try:
+ AsynchXendClientProtocol
+ except:
+ from XendAsynchProtocol import AsynchXendClientProtocol
+ return AsynchXendClientProtocol
+
+def getAsynchServer():
+ """Load AsynchXendClientProtocol and create an asynch xend client.
+
+ @return asynch Xend
+ """
+ getAsynchXendClientProtocol()
+ return Xend(AsynchXendClientProtocol())
+
def xendmain(srv, asynch, fn, args):
if asynch:
- client = AsynchXendClientProtocol()
+ getAsynchXendClientProtocol()
+ client = AsynchXendClientProtocol()
else:
client = None
xend = Xend(srv=srv, client=client)
main(sys.argv)
else:
server = Xend()
- aserver = Xend( AsynchXendClientProtocol() )
--- /dev/null
+# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
+
+import httplib
+import types
+
+from encode import *
+import sxp
+
+DEBUG = 0
+
+HTTP_OK = 200
+HTTP_CREATED = 201
+HTTP_ACCEPTED = 202
+HTTP_NO_CONTENT = 204
+
+class XendError(RuntimeError):
+ """Error class for 'expected errors' when talking to xend.
+ """
+ pass
+
+class XendRequest:
+ """A request to xend.
+ """
+
+ def __init__(self, url, method, args):
+ """Create a request. Sets up the headers, argument data, and the
+ url.
+
+ @param url: the url to request
+ @param method: request method, GET or POST
+ @param args: dict containing request args, if any
+ """
+ if url.proto != 'http':
+ raise ValueError('Invalid protocol: ' + url.proto)
+ (hdr, data) = encode_data(args)
+ if args and method == 'GET':
+ url.query = data
+ data = None
+ if method == "POST" and url.path.endswith('/'):
+ url.path = url.path[:-1]
+
+ self.headers = hdr
+ self.data = data
+ self.url = url
+ self.method = method
+
+class XendClientProtocol:
+ """Abstract class for xend clients.
+ """
+ def xendRequest(self, url, method, args=None):
+ """Make a request to xend.
+ Implement in a subclass.
+
+ @param url: xend request url
+ @param method: http method: POST or GET
+ @param args: request arguments (dict)
+ """
+ raise NotImplementedError()
+
+ def xendGet(self, url, args=None):
+ """Make a xend request using HTTP GET.
+ Requests using GET are usually 'safe' and may be repeated without
+ nasty side-effects.
+
+ @param url: xend request url
+ @param data: request arguments (dict)
+ """
+ return self.xendRequest(url, "GET", args)
+
+ def xendPost(self, url, args):
+ """Make a xend request using HTTP POST.
+ Requests using POST potentially cause side-effects, and should
+ not be repeated unless you really want to repeat the side
+ effect.
+
+ @param url: xend request url
+ @param args: request arguments (dict)
+ """
+ return self.xendRequest(url, "POST", args)
+
+ def handleStatus(self, version, status, message):
+ """Handle the status returned from the request.
+ """
+ status = int(status)
+ if status in [ HTTP_NO_CONTENT ]:
+ return None
+ if status not in [ HTTP_OK, HTTP_CREATED, HTTP_ACCEPTED ]:
+ return self.handleException(XendError(message))
+ return 'ok'
+
+ def handleResponse(self, data):
+ """Handle the data returned in response to the request.
+ """
+ if data is None: return None
+ type = self.getHeader('Content-Type')
+ if type != sxp.mime_type:
+ return data
+ try:
+ pin = sxp.Parser()
+ pin.input(data);
+ pin.input_eof()
+ val = pin.get_val()
+ except sxp.ParseError, err:
+ return self.handleException(err)
+ if isinstance(val, types.ListType) and sxp.name(val) == 'xend.err':
+ err = XendError(val[1])
+ return self.handleException(err)
+ return val
+
+ def handleException(self, err):
+ """Handle an exception during the request.
+ May be overridden in a subclass.
+ """
+ raise err
+
+ def getHeader(self, key):
+ """Get a header from the response.
+ Case is ignored in the key.
+
+ @param key: header key
+ @return: header
+ """
+ raise NotImplementedError()
+
+class SynchXendClientProtocol(XendClientProtocol):
+ """A synchronous xend client. This will make a request, wait for
+ the reply and return the result.
+ """
+
+ resp = None
+
+ def xendRequest(self, url, method, args=None):
+ """Make a request to xend.
+
+ @param url: xend request url
+ @param method: http method: POST or GET
+ @param args: request arguments (dict)
+ """
+ self.request = XendRequest(url, method, args)
+ conn = httplib.HTTPConnection(url.location())
+ if DEBUG: conn.set_debuglevel(1)
+ conn.request(method, url.fullpath(), self.request.data, self.request.headers)
+ resp = conn.getresponse()
+ self.resp = resp
+ val = self.handleStatus(resp.version, resp.status, resp.reason)
+ if val is None:
+ data = None
+ else:
+ data = resp.read()
+ conn.close()
+ val = self.handleResponse(data)
+ return val
+
+ def getHeader(self, key):
+ return self.resp.getheader(key)
+